package com.ruoyi.socket.config;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.Random;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * 币安WebSocket代理配置类
 * 支持动态随机数生成和超时管理
 */
@Component
@ConfigurationProperties(prefix = "binance.proxy")
@Data
@Slf4j
public class BinanceProxyConfig {

    /**
     * 代理是否启用
     */
    private boolean enabled = false;

    /**
     * 代理主机地址
     */
    private String host;

    /**
     * 代理端口
     */
    private int port;

    /**
     * 用户名模板（包含{random}占位符）
     */
    private String usernameTemplate;

    /**
     * 密码
     */
    private String password;

    /**
     * 超时时间（分钟）
     */
    private int timeout = 30;

    /**
     * 当前生成的随机数
     */
    private volatile String currentRandom;

    /**
     * 随机数生成时间
     */
    private volatile LocalDateTime randomGeneratedTime;

    /**
     * 定时任务执行器
     */
    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

    /**
     * 随机数生成器
     */
    private final Random random = new Random();

    @PostConstruct
    public void init() {
        if (enabled) {
            log.info("币安代理配置已启用，主机: {}:{}", host, port);
            // 初始化随机数
            generateNewRandom();
            // 启动定时检查任务
            startRandomUpdateTask();
        } else {
            log.info("币安代理配置未启用");
        }
    }

    /**
     * 生成新的8位随机数
     */
    public synchronized void generateNewRandom() {
        // 生成8位随机数字
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 8; i++) {
            sb.append(random.nextInt(10));
        }
        
        String newRandom = sb.toString();
        String oldRandom = currentRandom;
        
        currentRandom = newRandom;
        randomGeneratedTime = LocalDateTime.now();
        
        log.info("生成新的随机数: {} -> {}, 生成时间: {}", 
                oldRandom, newRandom, randomGeneratedTime);
    }

    /**
     * 检查随机数是否超时
     */
    public boolean isRandomExpired() {
        if (randomGeneratedTime == null) {
            return true;
        }
        
        LocalDateTime now = LocalDateTime.now();
        long minutesElapsed = ChronoUnit.MINUTES.between(randomGeneratedTime, now);
        
        return minutesElapsed >= timeout;
    }

    /**
     * 获取当前有效的用户名
     */
    public String getCurrentUsername() {
        if (!enabled || usernameTemplate == null) {
            return null;
        }
        
        // 检查是否需要更新随机数
        if (isRandomExpired()) {
            generateNewRandom();
        }
        
        return usernameTemplate.replace("{random}", currentRandom);
    }

    /**
     * 启动随机数更新定时任务
     */
    private void startRandomUpdateTask() {
        // 每分钟检查一次是否需要更新随机数
        scheduler.scheduleAtFixedRate(() -> {
            try {
                if (isRandomExpired()) {
                    log.info("随机数已超时，自动生成新随机数");
                    generateNewRandom();
                }
            } catch (Exception e) {
                log.error("随机数更新任务执行失败", e);
            }
        }, 1, 1, TimeUnit.MINUTES);
    }

    /**
     * 获取代理配置信息（用于日志）
     */
    public String getProxyInfo() {
        if (!enabled) {
            return "代理未启用";
        }
        
        return String.format("代理: %s:%d, 用户: %s, 超时: %d分钟, 当前随机数: %s", 
                host, port, getCurrentUsername(), timeout, currentRandom);
    }

    /**
     * 验证代理配置是否有效
     */
    public boolean isValidConfig() {
        if (!enabled) {
            return true; // 未启用时认为配置有效
        }
        
        return host != null && !host.trim().isEmpty() && 
               port > 0 && port <= 65535 && 
               usernameTemplate != null && !usernameTemplate.trim().isEmpty() && 
               password != null && !password.trim().isEmpty() && 
               timeout > 0;
    }

    /**
     * 获取剩余有效时间（分钟）
     */
    public long getRemainingMinutes() {
        if (randomGeneratedTime == null) {
            return 0;
        }
        
        LocalDateTime now = LocalDateTime.now();
        long minutesElapsed = ChronoUnit.MINUTES.between(randomGeneratedTime, now);
        
        return Math.max(0, timeout - minutesElapsed);
    }

    /**
     * 手动刷新随机数
     */
    public void refreshRandom() {
        log.info("手动刷新随机数");
        generateNewRandom();
    }

    /**
     * 关闭定时任务
     */
    public void shutdown() {
        if (scheduler != null && !scheduler.isShutdown()) {
            scheduler.shutdown();
            log.info("币安代理配置定时任务已关闭");
        }
    }
} 